﻿using MongoDB.Driver;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Entity.Core.Metadata.Edm;
using System.IO;
using System.Linq;
using System.Web;
using System.Security;
using MongoDB.Bson.Serialization.Attributes;

namespace SignatureWebApi
{
    /// <summary>
    /// DBinstanceClass
    /// </summary>
    public class SignatureMongoDbInstance
    {
        /// <summary>
        /// 外部使用的实例
        /// </summary>
        //public MongoClient Client;
        private MongoClient _CLinet;
        private  string _dataBaseName;
        /// <summary>
        /// 创建MongoDB实例
        /// </summary>
        /// <param name="hostname">MongoDB所在主机地址</param>
        /// <param name="port">连接端口</param>
        /// <param name="user">用户名</param>
        /// <param name="password">密码</param>
        /// <param name="dataBaseName">连接的数据库名称</param>
        public  SignatureMongoDbInstance(string hostname, int port, string user, string password, string dataBaseName)
        {
            char[] pChar = password.ToCharArray();
            SecureString securepassword = new SecureString();
            foreach (char c in pChar)
            {
                securepassword.AppendChar(c);
            }
            var mongoClientSettings = new MongoClientSettings
            {
                Credential = MongoCredential.CreateCredential(dataBaseName, user, securepassword),
                Server = new MongoServerAddress(hostname, port)
            };
            //Client = new MongoClient(mongoClientSettings);
            //_CLinet = Client;
            _CLinet = new MongoClient(mongoClientSettings);
            _dataBaseName = dataBaseName;
        }
        /// <summary>
        /// 插入Document(指定数据库)
        /// </summary>
        /// <param name="database"></param>
        /// <param name="collection"></param>
        /// <param name="addContent"></param>
        /// <returns></returns>
        public int InsertSingleDocument(string database, string collection, BsonDocument addContent)
        {
            int result = 0;
            TimeSpan timeSpent = TimeSpan.FromSeconds(15);
            var writeOption = new WriteConcern(WriteConcern.WValue.Parse("1"), timeSpent,null,true);
            var _database = _CLinet.WithWriteConcern(writeOption).GetDatabase(database);
            var _collection = _database.GetCollection<BsonDocument>(collection);
            try
            {
               
                _collection.InsertOne(addContent);
                result = 1;
            }
            catch (Exception e)
            {
                //throw;
                Console.WriteLine(e);
                result = 0;
            }
            return result;
        }
        /// <summary>
        /// 插入document(使用连接用户所在的数据库)
        /// </summary>
        /// <param name="collection"></param>
        /// <param name="addContent"></param>
        /// <returns></returns>
        public int InsertSingleDocument(string collection, BsonDocument addContent)
        {
            int result = 0;
            var _database = _CLinet.GetDatabase(_dataBaseName);
            var _collection = _database.GetCollection<BsonDocument>(collection);
            try
            {
                _collection.InsertOne(addContent);
                result = 1;
            }
            catch (Exception e)
            {
                //throw;
                Console.WriteLine(e);
                result = 0;
            }
            return result;
        }
        /// <summary>
        /// 删除单个匹配的document(指定数据库)
        /// </summary>
        /// <param name="database"></param>
        /// <param name="collection"></param>
        /// <param name="filter"></param>
        /// <returns></returns>
        public int DelSingleDocument(string database, string collection, BsonDocument filter)
        {
            int result = 0;
            long resultLong = 0;
            var _database = _CLinet.GetDatabase(database);
            var _collection = _database.GetCollection<BsonDocument>(collection);
            try
            {
                resultLong = _collection.DeleteOne(filter).DeletedCount;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                //throw;
                resultLong = 0;
            }

            result = Convert.ToInt32(resultLong);
            return result;
        }
        /// <summary>
        /// 删除单个匹配的document(指定数据库)
        /// </summary>
        /// <param name="database"></param>
        /// <param name="collection"></param>
        /// <param name="filter"></param>
        /// <returns></returns>
        public int DelSingleDocument(string database, string collection, FilterDefinition<BsonDocument> filter)
        {
            int result = 0;
            long resultLong = 0;
            var _database = _CLinet.GetDatabase(database);
            var _collection = _database.GetCollection<BsonDocument>(collection);
            try
            {
                resultLong = _collection.DeleteOne(filter).DeletedCount;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                //throw;
                resultLong = 0;
            }

            result = Convert.ToInt32(resultLong);
            return result;
        }
        /// <summary>
        /// 删除所有匹配的Document(指定数据库),并返回删除的个数
        /// </summary>
        /// <param name="database"></param>
        /// <param name="collection"></param>
        /// <param name="filter"></param>
        /// <returns></returns>
        public int DelDocuments(string database, string collection, BsonDocument filter)
        {
            int result = 0;
            long resultLong = 0;
            var _database = _CLinet.GetDatabase(database);
            var _collection = _database.GetCollection<BsonDocument>(collection);
            try
            {
                resultLong = _collection.DeleteMany(filter).DeletedCount;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                //throw;
                resultLong = 0;
            }

            result = Convert.ToInt32(resultLong);
            return result;
        }
        public int DelDocuments(string database, string collection, FilterDefinition<BsonDocument> filter)
        {
            int result = 0;
            long resultLong = 0;
            var _database = _CLinet.GetDatabase(database);
            var _collection = _database.GetCollection<BsonDocument>(collection);
            try
            {
                resultLong = _collection.DeleteMany(filter).DeletedCount;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                //throw;
                resultLong = 0;
            }

            result = Convert.ToInt32(resultLong);
            return result;
        }
        /// <summary>
        /// 更新单个匹配的document(指定数据库)
        /// </summary>
        /// <param name="database"></param>
        /// <param name="collection"></param>
        /// <param name="filter"></param>
        /// <param name="updateContent"></param>
        /// <returns></returns>
        public int UpdateSingleDocument(string database, string collection, BsonDocument filter, BsonDocument updateContent)
        {
            int result = 0;
            long resultLong = 0;
            TimeSpan timeSpent = TimeSpan.FromSeconds(15);
            var writeOption = new WriteConcern(WriteConcern.WValue.Parse("1"), timeSpent, null, true);
            var _database = _CLinet.GetDatabase(database);
            var _collection = _database.WithWriteConcern(writeOption).GetCollection<BsonDocument>(collection);
            var update = new BsonDocument("$set", updateContent);
            try
            {
                resultLong = _collection.UpdateOne(filter, update).ModifiedCount;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                //throw;
                resultLong = 0;
            }

            result = Convert.ToInt32(resultLong);
            return result;
        }
        /// <summary>
        /// 更新单个文档(filter指定类型)
        /// </summary>
        /// <param name="database"></param>
        /// <param name="collection"></param>
        /// <param name="filter"></param>
        /// <param name="updateContent"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public int UpdateSingleDocument<T>(string database, string collection, FilterDefinition<T> filter, BsonDocument updateContent)
        {
            int result = 0;
            long resultLong = 0;
            TimeSpan timeSpent = TimeSpan.FromSeconds(15);
            var writeOption = new WriteConcern(WriteConcern.WValue.Parse("1"), timeSpent, null, true);
            var _database = _CLinet.GetDatabase(database);
            var _collection = _database.WithWriteConcern(writeOption).GetCollection<T>(collection);
            var update = new BsonDocument("$set", updateContent);
            try
            {
                resultLong = _collection.UpdateOne(filter, update).ModifiedCount;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                //throw;
                resultLong = 0;
            }

            result = Convert.ToInt32(resultLong);
            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="database"></param>
        /// <param name="collection"></param>
        /// <param name="filter"></param>
        /// <param name="updateContent"></param>
        /// <param name="options"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public int UpdateSingleDocument<T>(string database, string collection, FilterDefinition<T> filter, BsonDocument updateContent, UpdateOptions options = null)
        {
            int result = 0;
            long resultLong = 0;
            TimeSpan timeSpent = TimeSpan.FromSeconds(15);
            var writeOption = new WriteConcern(WriteConcern.WValue.Parse("1"), timeSpent, null, true);
            var _database = _CLinet.GetDatabase(database);
            var _collection = _database.WithWriteConcern(writeOption).GetCollection<T>(collection);
            var update = new BsonDocument("$set", updateContent);
            try
            {
                resultLong = options == null ? _collection.UpdateOne(filter, update).ModifiedCount : _collection.UpdateOne(filter, update, options).ModifiedCount;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                //throw;
                resultLong = 0;
            }

            result = Convert.ToInt32(resultLong);
            return result;
        }
        /// <summary>
        /// 更新单个文档(filter指定类型,更新内容指定类型,可指定更新选项)
        /// </summary>
        /// <param name="database"></param>
        /// <param name="collection"></param>
        /// <param name="filter"></param>
        /// <param name="updateContent"></param>
        /// <param name="options"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public int UpdateSingleDocument<T>(string database, string collection, FilterDefinition<T> filter, UpdateDefinition<T> updateContent, UpdateOptions options = null)
        {
            int result = 0;
            long resultLong = 0;
            TimeSpan timeSpent = TimeSpan.FromSeconds(15);
            var writeOption = new WriteConcern(WriteConcern.WValue.Parse("1"), timeSpent, null, true);
            var _database = _CLinet.GetDatabase(database);
            var _collection = _database.WithWriteConcern(writeOption).GetCollection<T>(collection);
            try
            {
                resultLong = options == null ? _collection.UpdateOne(filter, updateContent).ModifiedCount : _collection.UpdateOne(filter, updateContent, options).ModifiedCount;

            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                //throw;
                resultLong = 0;
            }

            result = Convert.ToInt32(resultLong);
            return result;
        }
        /// <summary>
        /// 更新所有匹配的document(指定数据库),返回更新的个数
        /// </summary>
        /// <param name="database"></param>
        /// <param name="collection"></param>
        /// <param name="filter"></param>
        /// <param name="updateContent"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        public int UpdateDocument<T>(string database, string collection, FilterDefinition<T> filter, UpdateDefinition<T> updateContent, UpdateOptions options=null)
        {
            int result = 0;
            long resultLong = 0;
            TimeSpan timeSpent = TimeSpan.FromSeconds(15);
            var writeOption = new WriteConcern(WriteConcern.WValue.Parse("1"), timeSpent, null, true);
            var _database = _CLinet.GetDatabase(database);
            var _collection = _database.WithWriteConcern(writeOption).GetCollection<T>(collection);
            //var update = new BsonDocument("$set", updateContent);
            try
            {
                resultLong = options ==null? _collection.UpdateMany(filter, updateContent).ModifiedCount: _collection.UpdateMany(filter, updateContent, options).ModifiedCount;
                
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                //throw;
                resultLong = 0;
            }
            result = Convert.ToInt32(resultLong);
            return result;
        }
        /// <summary>
        /// 查找并更新一个记录
        /// </summary>
        /// <param name="database"></param>
        /// <param name="collection"></param>
        /// <param name="filter"></param>
        /// <param name="updateContent"></param>
        /// <param name="options"></param>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TProjection"></typeparam>
        /// <returns></returns>
        public TProjection FindOneAndUpdate<T, TProjection>(string database, string collection, FilterDefinition<T> filter, UpdateDefinition<T> updateContent, FindOneAndUpdateOptions<T, TProjection> options=null)
        {
            //int result = 0;
            //long resultLong = 0;
            TimeSpan timeSpent = TimeSpan.FromSeconds(15);
            var writeOption = new WriteConcern(WriteConcern.WValue.Parse("1"), timeSpent, null, true);
            var _database = _CLinet.GetDatabase(database);
            var _collection = _database.WithWriteConcern(writeOption).GetCollection<T>(collection);
            
            return _collection.FindOneAndUpdate(filter, updateContent,options) ;
            
        }
        /// <summary>
        /// 查找并更新一个记录(用Bsondocument)
        /// </summary>
        /// <param name="database"></param>
        /// <param name="collection"></param>
        /// <param name="filter"></param>
        /// <param name="updateContent"></param>
        /// <param name="options"></param>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TProjection"></typeparam>
        /// <returns></returns>
        public TProjection FindOneAndUpdate<T, TProjection>(string database, string collection, FilterDefinition<T> filter, BsonDocument updateContent, FindOneAndUpdateOptions<T, TProjection> options = null)
        {
            //int result = 0;
            //long resultLong = 0;
            TimeSpan timeSpent = TimeSpan.FromSeconds(15);
            var writeOption = new WriteConcern(WriteConcern.WValue.Parse("1"), timeSpent, null, true);
            var _database = _CLinet.GetDatabase(database);
            var _collection = _database.WithWriteConcern(writeOption).GetCollection<T>(collection);
            var update = new BsonDocument("$set", updateContent);
            return _collection.FindOneAndUpdate(filter, update, options);

        }
        /// <summary>
        /// 获取所有匹配的数据(指定数据库,指定序列化类型)
        /// </summary>
        /// <param name="database"></param>
        /// <param name="collection"></param>
        /// <param name="filter"></param>
        /// <param name="sort"></param>
        /// <param name="skip"></param>
        /// <param name="limit"></param>
        /// <param name="projection"></param>
        /// <returns>空返回null</returns>
        public IEnumerable GetDataMany<T, TResult>(string database, string collection, FilterDefinition<T> filter,SortDefinition<T> sort=null,int skip=0,int limit = 0, ProjectionDefinition<T, TResult> projection=null)
        {
            //List<T> rows = new List<T>();
            var _database = _CLinet.GetDatabase(database);
            IMongoCollection<T> _collection;
            try
            {
                 _collection = _database.GetCollection<T>(collection);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }

            //var _collection = _database.GetCollection<T>(collection);
            var result = sort == null ? _collection.Find(filter) : _collection.Find(filter).Sort(sort);
            result = skip > 0 ? result.Skip(skip) : result;
            result = limit > 0 ? result.Limit(limit) : result;
            if (projection != null)
            {
                return result.Project(projection).ToEnumerable();
            }
            return result.ToEnumerable();
        }
        /// <summary>
        /// 获取匹配的聚合数据(指定数据库,指定源数据类型和输出数据类型)
        /// </summary>
        /// <param name="database"></param>
        /// <param name="collection"></param>
        /// <param name="pipeline"></param>
        /// <returns>空返回null</returns>
        public IEnumerable GetDataAggregate<T,TResult>(string database, string collection, PipelineDefinition<T, TResult> pipeline)
        {
            //List<T> rows = new List<T>();
            IMongoDatabase _database;
            IMongoCollection<T> _collection;
            try
            {
                 _database = _CLinet.GetDatabase(database);
                _collection = _database.GetCollection<T>(collection);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
            //var _database = _CLinet.GetDatabase(database);
            //var _collection = _database.GetCollection<T>(collection);
            return _collection.Aggregate(pipeline).ToList().ToArray();


        }
        /// <summary>
        /// 获取所有匹配的数据(指定数据库,返回默认List类型)
        /// </summary>
        /// <param name="database"></param>
        /// <param name="collection"></param>
        /// <param name="filter"></param>
        /// <returns>空返回null</returns>
        public List<Dictionary<string, string>> GetDataMany(string database, string collection, BsonDocument filter)
        {
            List<Dictionary<string, string>> rows = null;
            var _database = _CLinet.GetDatabase(database);
            var _collection = _database.GetCollection<BsonDocument>(collection);
            try
            {
                using (var cursor = _collection.Find(filter).ToCursor())
                {

                    rows = new List<Dictionary<string, string>>();
                    while (cursor.MoveNext())
                    {
                        foreach (var document in cursor.Current)
                        {
                            var row = new Dictionary<string, string>();
                            foreach (var element in document)
                            {
                                var columnName = element.Name;
                                var columnValue = element.Value.ToString();
                                row.Add(columnName, columnValue);
                            }

                            rows.Add(row);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                rows = null;
                Console.WriteLine(e);
            }

            return rows;
        }
        /// <summary>
        /// 获取单个匹配的数据(指定数据库)
        /// </summary>
        /// <param name="database"></param>
        /// <param name="collection"></param>
        /// <param name="filter"></param>
        /// <returns>如有多个匹配,返回第一个</returns>
        public Dictionary<string, object> GetDataSingel( string database, string collection, BsonDocument filter)
        {
            Dictionary<string, object> row = null;
            var _database = _CLinet.GetDatabase(database);
            var _collection = _database.GetCollection<BsonDocument>(collection);
            /*var filter = new BsonDocument(parameters);*/
            try
            {
                using (var cursor = _collection.Find(filter).Limit(1).ToCursor())
                {

                    while (cursor.MoveNext())
                    {
                        foreach (var document in cursor.Current)
                        {
                            row = new Dictionary<string, object>();
                            foreach (var element in document)
                            {
                                var columnName = element.Name;
                                var columnValue = element.Value;
                                row.Add(columnName, columnValue);
                            }

                            
                        }
                    }
                }
            }
            catch (Exception e)
            {
                row = null;
                Console.WriteLine(e);
            }

            return row;
        }
        /// <summary>
        /// 获取单个匹配的数据(指定数据库,指定filter类型和projection类型(默认null))
        /// </summary>
        /// <param name="database"></param>
        /// <param name="collection"></param>
        /// <param name="filter"></param>
        /// <param name="projection"></param>
        /// <param name="sort"></param>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TResult"></typeparam>
        /// <returns></returns>
        public IEnumerable GetDataSingel<T, TResult>(string database, string collection, FilterDefinition<T> filter,ProjectionDefinition<T, TResult> projection = null,SortDefinition<T> sort=null)
        {
            var _database = _CLinet.GetDatabase(database);
            var _collection = _database.GetCollection<T>(collection);
            //IFindFluent<T, T> result;
            var result = sort == null ? _collection.Find(filter).Limit(1) : _collection.Find(filter).Sort(sort).Limit(1);
            if (projection != null)
            {
               
                return result.Project(projection).ToEnumerable();
            }
            return result.ToEnumerable();
        }
        /// <summary>
        /// 返回匹配数据的数量(指定数据库)
        /// </summary>
        /// <param name="database"></param>
        /// <param name="collection"></param>
        /// <param name="filter"></param>
        /// <param name="soft"></param>
        /// <param name="skip"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        public long CountData<T>(string database, string collection, FilterDefinition<T> filter, SortDefinition<T> soft = null, int skip = 0, int limit = 0)
        {
            var _database = _CLinet.GetDatabase(database);
            var _collection = _database.GetCollection<T>(collection);
            var result = soft == null ? _collection.Find(filter) : _collection.Find(filter).Sort(soft);
            result = skip > 0 ? result.Skip(skip) : result;
            result = limit > 0 ? result.Limit(limit) : result;
            return result.Count();
        }
    }

    /// <summary>
    /// 储存数据库的硬代码(Release)
    /// </summary>
    public static class DbConnString1
    {
        //DbConnString.FlightDatabase
        /// <summary>
        /// 签单数据库IP地址
        /// </summary>
        public static readonly string SignatureIpAdress = "10.1.11.102";

        /// <summary>
        /// 用户认证数据库IP地址
        /// </summary>
        public static readonly string IdentityIpAdress = "10.1.11.102";

        /// <summary>
        /// 航班数据库IP地址
        /// </summary>
        public static readonly string FlightIpAdress = "10.1.11.102";

        /// <summary>
        /// 后台任务数据库IP地址
        /// </summary>
        public static readonly string BackgroundProcessIpAdress = "10.1.11.102";

        
        /// <summary>
        /// 签单数据库名
        /// </summary>
        public static readonly string SignatureDatabase = "DataStore";

        /// <summary>
        /// 用户认证数据库名
        /// </summary>
        public static readonly string IdentityDatabase = "Users";

        /// <summary>
        /// 航班数据数据库名
        /// </summary>
        public static readonly string FlightDatabase = "monitor_t2";
        /// <summary>
        /// 航班数据数据库名
        /// </summary>
        public static readonly string BackgroundProcessDatabase = "BackgroundProcess";
    }

    /// <summary>
    /// 储存数据库的硬代码(Debug)
    /// </summary>
    public static class DbConnString
    {
        //DbConnString.FlightDatabase
        /// <summary>
        /// 签单数据库IP地址
        /// </summary>
        public static readonly string SignatureIpAdress = "172.18.0.102";//localhost

        /// <summary>
        /// 用户认证数据库IP地址
        /// </summary>
        public static readonly string IdentityIpAdress = "172.18.0.102";//localhost

        /// <summary>
        /// 航班数据库IP地址
        /// </summary>
        public static readonly string FlightIpAdress = "172.18.0.102";

        /// <summary>
        /// 后台任务数据库IP地址
        /// </summary>
        public static readonly string BackgroundProcessIpAdress = "172.18.0.102";//localhost


        /// <summary>
        /// 签单数据库名
        /// </summary>
        public static readonly string SignatureDatabase = "DataStore";

        /// <summary>
        /// 用户认证数据库名
        /// </summary>
        public static readonly string IdentityDatabase = "Users";

        /// <summary>
        /// 航班数据数据库名
        /// </summary>
        public static readonly string FlightDatabase = "monitor";
        /// <summary>
        /// 航班数据数据库名
        /// </summary>
        public static readonly string BackgroundProcessDatabase = "BackgroundProcess";
    }
   
    /// <summary>
    /// 航班数据库连接账号(release)
    /// </summary>
    public static class FlightDatabaseConnAcount
    {
        /// <summary>
        /// 
        /// </summary>
        public static readonly string FlightDatabaseUser = "monitorT2User";

        /// <summary>
        /// 
        /// </summary>
        public static readonly string FlightDatabasePassword = "T2dengjiqiao";
    }
     
    /// <summary>
    /// 航班数据库连接账号(Debug)
    /// </summary>
    public static class FlightDatabaseConnAcount1
    {
        /// <summary>
        /// 
        /// </summary>
        public static readonly string FlightDatabaseUser = "monitorUser";

        /// <summary>
        /// 
        /// </summary>
        public static readonly string FlightDatabasePassword = "Moni658457!";
    }

    ///// <summary>
    ///// 保存MongoDB实例的静态类
    ///// </summary>
    //public static class MongoDbInstanceStore{
    //    public static SignatureMongoDbInstance Client1;
    //    public static SignatureMongoDbInstance DataStoreInstance;
    //    public static SignatureMongoDbInstance FlightMergeInstance;
    //}
    //public static class RecurringTask
    //{
    //    public static void Job1()
    //    {
    //        var ttt = MongoDbInstanceStore.FlightMergeInstance;
    //        var builder = Builders<BsonDocument>.Filter;
    //        FilterDefinition<BsonDocument> filter;
    //        filter = builder.Empty;

    //        filter &= builder.Gte("u_t", new BsonDateTime(Convert.ToDateTime("2018-3-22 10:00:00")));
    //        var stringg = ttt.GetDataMany<BsonDocument, BsonDocument>("monitor", "coll_flight_merge", filter);

    //    }
    //}
}